#pragma once

#include "Serializable.h"

#include <string>

class Team;
class ZStream;

enum EPlayerRole
{
	Goalkeeper = 0,
	Defender = 1,
	Attacker = 2,
	NUM_ROLES = 3
};

struct PlayerParams
{
	size_t	MAX_CHAR_PLAYER_NAME;
	size_t	DAILY_FATIGUE_RECOVER;
	size_t	MIN_SKILL_VALUE;
	float	SELL_FACTOR;
	float	BUY_FACTOR;
};

struct PlayerSkills
{
	void Serialize(ZStream& o_stream);
	void Deserialize(ZStream& i_stream);
	void CalculateBestRole();

	int m_roleSkills[NUM_ROLES];
	int m_fatigue;
	int m_resistance;
	int m_bestRole;
};

class Player : public Serializable
{
public:
	Player(){}
	Player(const std::string& i_name, const size_t i_id);

	size_t GetId() const;
	int GetAge() const;
	const std::string& GetName() const;
	void SetTeam(Team* const i_team);
	Team* const GetTeam() const;
	const std::string& GetTeamName() const;
	int GetSalary() const;
	int BuyValue() const;
	int SellValue() const;

	int	GetBestRole() const;
	void SetRole(const int i_role);
	const PlayerSkills& GetSkills() const;
	int GetAverageSkill() const;
	int GetSkill(const int i_playingRole) const;
	void PostMatchUpdateSkills(const int i_playedRole);

	bool IsBroken() const;
	int GetDaysUnavaiable() const;
	int GetNumOfInjury() const;
	bool InjuryTest(const bool i_isTired);
	void Heal();
	int GetFatigue() const;
	void UpdateFatigue(const int i_fatigue);
	float CalculateStamina() const;
	
	void ScoreGoal();
	size_t GetScoredGoal() const;
	size_t GetTotalScoredGoal() const;
	void AddPlayedMatch();
	size_t GetPlayedMatch() const;
	size_t GetTotalPlayedMatch() const;
	float GetScoredGoalRatio() const;
	std::string GetScoredGoalRatioStr() const;
	float GetTotalScoredGoalRatio() const;
	std::string GetTotalScoredGoalRatioStr() const;
	size_t GetNumSeason() const;
	int GetRetirementYear() const;
	void SetRetirementYear(const int i_retirementYear);
	bool IsRetired() const;

	bool SeasonUpdate();

	static const PlayerParams& GetPlayerParams();
	static const int NUM_HOF_PLAYERS = 200;

	virtual	ZStream& Serialize(ZStream& o_stream);
	virtual ZStream& Deserialize(ZStream& i_stream);

private:
	static PlayerParams s_params;
	static const int MAX_DAY_OFF = 33;

	size_t m_id;
	int m_age;
	std::string m_name;
	int m_salary;

	PlayerSkills m_skill;

	int m_daysUnavailable;
	int m_numOfInjury;
	
	Team* m_team;

	size_t m_scoredGoal;
	size_t m_historyScoredGoal;
	size_t m_playedMatch;
	size_t m_historyPlayedMatch;

	size_t m_numSeason;
	int m_retirementYear;

	void Generate(const std::string& i_name, const size_t i_id);
	void CalculateSalary();
	void EndSeason();
	bool CheckRetirment() const;
	int GetDefaultInjuryChance() const ;
	void PostMatchUpdateSkill(int& o_skill, const bool i_up, const bool i_play);
	void PostMatchUpdateResistance(const bool i_up);
	void TryUpSkill(int& o_skill, const int i_diceRoll);

	friend class PlayerManager;
};

#include "Player.inl"